home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / utilitys / ed3_1_1 / part02 / create.c next >
C/C++ Source or Header  |  1991-11-07  |  17KB  |  754 lines

  1. /*
  2.     These are polygon creation funtions of ed3.
  3.  
  4. 10-22-91 add create_globe
  5. 10-16-91 all polyhedra except the pentagonal dodec are now created WITH faces
  6. 10-13-91 create_poly() now checks to see if there is room in the undo buf
  7. 09-06-91 adapted to use coord instead of short
  8. 09-02-91 add create_rhombic()
  9. 08-20-91 add code to contruct icos, dodec from radius OR edge length
  10. 08-19-91 add create_poly
  11.          add g_radius, g_edge_length
  12.          add code to contruct tet, oct, and cube from radius OR edge length
  13. 08-15-91 chg normalize() to call find_center and find_radius
  14. */
  15.  
  16. #include "sysnogr.h"
  17.  
  18. #define METHOD 2
  19.  
  20. char *poly_name[7] =
  21. {
  22.   "Tetrahedron",
  23.   "Octahedron",
  24.   "Cube",
  25.   "Icosahedron",
  26.   "Pentagonal Dodecahedron",
  27.   "Rhombic Dodecahedron",
  28.   "Cuboctahedron"
  29. };
  30.  
  31.  
  32. /* number of points for each polyhedron */
  33. short poly_points[7] =
  34. {
  35.     4,    6,    8,    12,    20,    14,    12
  36. };
  37.  
  38. /* number of triangular faces for each polyhedron */
  39. short poly_faces[7] =
  40. {
  41. /*    4,    8,    6,    20,    12,    12, 14     total facets */
  42.     4,    8,    0,    20,    0,    0,    8
  43. };
  44.  
  45. /* number of non-triangluar face for each polyhedron */
  46. short poly_polys[7] =
  47. {
  48.     0,    0,    6,    0,    12,    12,    6
  49. };
  50.  
  51. /* these 2 variables are used in every function in this module */
  52. /* g_ means global */
  53. long g_radius, g_edge_length;
  54.  
  55.  
  56. void create_poly(which_poly)
  57. int which_poly;
  58. {
  59.     int go = 1, event;
  60.     int id;
  61.     long data = 100, dimen = 100;
  62.  
  63.     char title[50];
  64.  
  65.     strcpy(title, "Create ");
  66.     strcat(title, poly_name[which_poly]);
  67.  
  68.     sys_window(34, 4, title);
  69.     sys_movecur(1,0);
  70.     sys_say_text("Dimension:");
  71.     sys_get_long(data, 1);
  72.     sys_movecur(1,1);
  73.     sys_say_text("Create: using this value as");
  74.     sys_movecur(1,2);
  75.     sys_say_text("the ");
  76.     sys_boolean("Edge Length", 2);
  77.     sys_say_text(" or ");
  78.     sys_boolean("Radius", 3);
  79.     sys_activate(1);
  80.  
  81.     while (go)
  82.     {
  83.         event = sys_read_event(&id, &data);
  84.         switch (event)
  85.         {
  86.         case EV_CANCEL:
  87.             sys_close_window();
  88.             return;
  89.             break;
  90.         case EV_CHECKINT:
  91.         case EV_HITRETURN:
  92.         case EV_HITBUTTON:
  93.             if (id == 1)
  94.             {
  95.                 if (data > 8000) data = 8000;
  96.                 if (data < 5) data = 5;
  97.                 dimen = data;
  98.             }
  99.             else if (id == 2)
  100.             {
  101.                 g_edge_length = dimen;
  102.                 g_radius = 0;
  103.                 go = 0;
  104.             }
  105.             else if (id == 3)
  106.             {
  107.                 g_edge_length = 0;
  108.                 g_radius = dimen;
  109.                 go = 0;
  110.             }
  111.             break;
  112.         }
  113.     }
  114.     sys_close_window();
  115.  
  116.     if (!enough_room(poly_points[which_poly],
  117.                      poly_faces[which_poly],
  118.                      poly_polys[which_poly],
  119.                      0, 0, 0, 0, 0))
  120.     {
  121.         /* this operation could overflow the undo buffer! */
  122.         if (!tell_user_overflow()) return;
  123.     }
  124.  
  125.     begin_operation();
  126.     switch (which_poly)
  127.     {
  128.         case POLY_TET:    create_tetra(1); break;
  129.         case POLY_OCT:    create_octa(1); break;
  130.         case POLY_CUBE:    create_cube(1); break;
  131.         case POLY_ICOS:    create_icosa(1); break;
  132.  
  133.         case POLY_DODEC:    create_dodec(1); break;
  134.         case POLY_RHOMB:    create_rhombic(1); break;
  135.         case POLY_CUBOCT:    create_cuboct(1); break;
  136.     }
  137.     end_operation();
  138. }
  139.  
  140.  
  141. /* all polyhedra created are centered at the origin */
  142.  
  143. void create_tetra(connected)
  144. int connected;
  145. {
  146.     double edge, radius, height,
  147.          face_radius;    /* radius of each triangular face */
  148.     coord top_z, base_z;
  149.     index f;    /* index on the first point created */
  150.  
  151.     if (g_edge_length)
  152.     {
  153.         edge = (double)g_edge_length;
  154.         radius = sqrt(3.)/(2.*sqrt(2.)) * edge;
  155.         height = sqrt(2./3.) * edge;
  156.         face_radius = 1./sqrt(3.) * edge;    /* radius of each triangular face */
  157.     }
  158.     else
  159.     {
  160.         radius = (double)g_radius;
  161.         edge = 2.*sqrt(2./3.) * radius;
  162.         height = 4./(3.*sqrt(3.)) * radius;
  163.         face_radius = 2.*sqrt(2.)/3. * radius;    /* radius of each triangular face */
  164.     }
  165.  
  166.     top_z = (coord)(.75 * height);
  167.     base_z = (coord)(-.25 * height);
  168.  
  169.     f = points;
  170.     add_point(zero, zero, top_z);        /* top */
  171.     add_point((coord)(-edge/2.), (coord)(-face_radius/2.), base_z);
  172.     add_point((coord)( edge/2.), (coord)(-face_radius/2.), base_z);
  173.     add_point(zero, (coord)face_radius, base_z);
  174.     convert_points();
  175.  
  176.     if (!connected) return;
  177.  
  178.     add_face1(f, f+1, f+2);
  179.     add_face1(f, f+2, f+3);
  180.     add_face1(f, f+3, f+1);
  181.     add_face1(f+1, f+2, f+3);
  182. }
  183.  
  184.  
  185. void create_octa(connected)
  186. int connected;
  187. {
  188.     double edge, radius;
  189.     coord r;
  190.     int f;
  191.  
  192.     if (g_radius)
  193.     {
  194.         radius = g_radius;
  195.         edge = sqrt(2.)*radius;
  196.     }
  197.     else
  198.     {
  199.         edge = g_edge_length;
  200.         radius = edge/sqrt(2.);
  201.     }
  202.  
  203.     r = radius;
  204.     f = points;
  205.     add_point(zero, zero,  r);
  206.     add_point(zero, zero, -r);
  207.     add_point(zero,  r, zero);
  208.     add_point(zero, -r, zero);
  209.     add_point( r, zero, zero);
  210.     add_point(-r, zero, zero);
  211.     convert_points();
  212.  
  213.     if (!connected) return;
  214.  
  215.     add_face1(f, f+2, f+4);
  216.     add_face1(f, f+4, f+3);
  217.     add_face1(f, f+3, f+5);
  218.     add_face1(f, f+5, f+2);
  219.  
  220.     add_face1(f+1, f+2, f+4);
  221.     add_face1(f+1, f+4, f+3);
  222.     add_face1(f+1, f+3, f+5);
  223.     add_face1(f+1, f+5, f+2);
  224. }
  225.  
  226.  
  227. void create_cube(connected)
  228. int connected;
  229. {
  230.     double edge, radius;
  231.     coord half;
  232.     index np[4];    /* new polygon */
  233.     index f;
  234.  
  235.     if (g_radius)
  236.     {
  237.         radius = g_radius;
  238.         edge = radius*2./sqrt(3.);
  239.     }
  240.     else
  241.     {
  242.         edge = g_edge_length;
  243.         radius = edge*sqrt(3.)/2;
  244.     }
  245.  
  246.     half = edge/2.;
  247.     f = points;
  248.     add_point( half,  half,  half);
  249.     add_point( half,  half, -half);
  250.     add_point( half, -half,  half);
  251.     add_point( half, -half, -half);
  252.     add_point(-half,  half,  half);
  253.     add_point(-half,  half, -half);
  254.     add_point(-half, -half,  half);
  255.     add_point(-half, -half, -half);
  256.     convert_points();
  257.  
  258.     if (!connected) return;
  259.  
  260.     np[0] = f; np[1] = f+1; np[2] = f+5; np[3] = f+4;
  261.     add_poly(4, colors.newface, np, 0);
  262.     np[0] = f; np[1] = f+2; np[2] = f+3; np[3] = f+1;
  263.     add_poly(4, colors.newface, np, 0);
  264.     np[0] = f; np[1] = f+4; np[2] = f+6; np[3] = f+2;
  265.     add_poly(4, colors.newface, np, 0);
  266.  
  267.     np[0] = f+7; np[1] = f+5; np[2] = f+1; np[3] = f+3;
  268.     add_poly(4, colors.newface, np, 0);
  269.     np[0] = f+7; np[1] = f+6; np[2] = f+4; np[3] = f+5;
  270.     add_poly(4, colors.newface, np, 0);
  271.     np[0] = f+7; np[1] = f+3; np[2] = f+2; np[3] = f+6;
  272.     add_poly(4, colors.newface, np, 0);
  273. }
  274.  
  275.  
  276. void create_icosa(connected)
  277. int connected;
  278. {
  279.     double edge, radius;
  280.     index f;
  281.  
  282. #ifdef METHOD1
  283.     double deg_x = 37. + (22./60.) + (38.527/3600.),    /* deg, min, sec. */
  284.            deg_phi = 31. + (43./60.) + (2.907/3600.),
  285.            deg_3 = 20. + (54./60.) + (18.566/3600.);
  286.     double r_x = deg_x * PI / 180.,                    /* convert to radians */
  287.            r_phi = deg_phi * PI / 180.,
  288.            r_3 = deg_3 * PI / 180.;
  289.     double phi, theta;
  290.     index i;
  291.     coord x, y, z;
  292. #else
  293.     double tau;
  294.     coord tau2, edg2;
  295. #endif
  296.  
  297.     if (g_edge_length)
  298.     {
  299.         edge = (double)g_edge_length;
  300.         radius = sqrt((5. + sqrt(5.0)) / 8.) * edge;
  301.     }
  302.     else
  303.     {
  304.         radius = (double)g_radius;
  305.         edge = sqrt(8. / (5. + sqrt(5.0))) * radius;
  306.     }
  307.  
  308.     f = points;
  309. #if METHOD == 1
  310.     add_point(zero, zero, (coord)radius);    /* top point */
  311.     add_point(zero, zero, (coord)-radius);    /* bottom point */
  312.  
  313.     phi = 2. * r_phi;                /* top pentagon , points 72deg apart */
  314.     for (i = 0; i < 5; i++)
  315.     {
  316.         theta = i * (.4 * PI);
  317.         x = radius * sin(phi) * cos(theta);
  318.         y = radius * sin(phi) * sin(theta);
  319.         z = radius * cos(phi);
  320.         add_point(x, y, z);
  321.     }
  322.  
  323.     phi = 2.*r_x + 2.*r_3;            /* bottom pentagon */
  324.     for (i = 0; i < 5; i++)
  325.     {
  326.         theta = i * (.4 * PI) + (.2*PI);    /* offset by 36deg */
  327.         x = radius * sin(phi) * cos(theta);
  328.         y = radius * sin(phi) * sin(theta);
  329.         z = radius * cos(phi);
  330.         add_point(x, y, z);
  331.     }
  332. #else
  333. /*
  334. The expression for the radius of an icosahedron with edge length 1 is
  335.   sqrt(t+2)/2, where t (usually called tau) is the golden mean
  336.     (1+sqrt(5))/2
  337. The coordinates of the vertices of an icosahedon of edge length 2 are:
  338.    (1,0,t), (t,1,0), (0,t,1), (-1,0,t), (0,-t,1), (t,-1,0),
  339.    and reverse all of the signs for the other six vertices.
  340. ******************************************************************************
  341.  Byron D. Biggs                           bdb9u@virginia.{EDU,BITNET}
  342. */
  343.     tau = (1.0+sqrt(5.0))/2.0;
  344.     tau2 = (coord)(tau / 2.0 * edge);    /* we divide by 2 for a unit edge */
  345.     edg2 = (coord)(edge / 2.0);
  346.  
  347.     add_point( edg2,  zero,  tau2);
  348.     add_point( edg2,  zero, -tau2);
  349.     add_point(-edg2,  zero,  tau2);
  350.     add_point(-edg2,  zero, -tau2);
  351.     add_point( zero,  tau2,  edg2);
  352.     add_point( zero,  tau2, -edg2);
  353.     add_point( zero, -tau2,  edg2);
  354.     add_point( zero, -tau2, -edg2);
  355.     add_point( tau2,  edg2,  zero);
  356.     add_point( tau2, -edg2,  zero);
  357.     add_point(-tau2,  edg2,  zero);
  358.     add_point(-tau2, -edg2,  zero);
  359. #endif
  360.     convert_points();
  361.  
  362.     if (!connected) return;
  363.  
  364.     add_face1(f+5, f+1, f+3);
  365.     add_face1(f+5, f+8, f+1);
  366.     add_face1(f+5, f+4, f+8);
  367.     add_face1(f+5, f+10, f+4);
  368.     add_face1(f+5, f+3, f+10);
  369.  
  370.     add_face1(f+10, f+3, f+11);
  371.     add_face1(f+3, f+7, f+11);
  372.     add_face1(f+3, f+1, f+7);
  373.     add_face1(f+1, f+9, f+7);
  374.     add_face1(f+1, f+8, f+9);
  375.  
  376.     add_face1(f+8, f+0, f+9);
  377.     add_face1(f+8, f+4, f+0);
  378.     add_face1(f+4, f+2, f+0);
  379.     add_face1(f+4, f+10, f+2);
  380.     add_face1(f+10, f+11, f+2);
  381.  
  382.     add_face1(f+2, f+11, f+6);
  383.     add_face1(f+11, f+7, f+6);
  384.     add_face1(f+7, f+9, f+6);
  385.     add_face1(f+9, f+0, f+6);
  386.     add_face1(f+0, f+2, f+6);
  387. }
  388.  
  389.  
  390. void create_dodec(connected)
  391. int connected;
  392. {
  393.     double    gold = (sqrt(5.)+1)/2.,
  394.             igold = 1./gold;
  395.     double edge, radius;
  396.     coord e, g, i;
  397.     index np[5];    /* new polygon */
  398.  
  399.     if (g_radius)
  400.     {
  401.         radius = g_radius;
  402.         edge = radius/sqrt(3.);
  403.     }
  404.     else
  405.     {
  406.         edge = g_edge_length;
  407.         radius = edge*sqrt(3.);
  408.     }
  409.     gold *= edge;
  410.     igold *= edge;
  411.  
  412.     e = (coord)edge;
  413.     g = (coord)gold;
  414.     i = (coord)igold;
  415.  
  416.     add_point(zero,  i,  g);
  417.     add_point(zero, -i,  g);
  418.     add_point(zero,  i, -g);
  419.     add_point(zero, -i, -g);
  420.  
  421.     add_point( g, zero,  i);
  422.     add_point( g, zero, -i);
  423.     add_point(-g, zero,  i);
  424.     add_point(-g, zero, -i);
  425.  
  426.     add_point( i,  g, zero);
  427.     add_point(-i,  g, zero);
  428.     add_point( i, -g, zero);
  429.     add_point(-i, -g, zero);
  430.  
  431.     /* this method of constructing a dodecahedron reveals an
  432.         inscribed cube */
  433.  
  434.     add_point(  e,  e,  e);
  435.     add_point(  e,  e, -e);
  436.     add_point(  e, -e,  e);
  437.     add_point(  e, -e, -e);
  438.     add_point( -e,  e,  e);
  439.     add_point( -e,  e, -e);
  440.     add_point( -e, -e,  e);
  441.     add_point( -e, -e, -e);
  442.  
  443.     convert_points();
  444.  
  445.     if (!connected) return;
  446.  
  447. }
  448.  
  449.  
  450. void create_rhombic(connected)
  451. int connected;
  452. {
  453.     double edge, radius;
  454.     double half;    /* inner radius */
  455.     coord ra, ha;
  456.     index f;
  457.     index np[4];    /* new polygon */
  458.  
  459.     if (g_radius)
  460.     {
  461.         radius = g_radius;
  462.         edge = radius / (2.0 * sqrt(3.));
  463.     }
  464.     else
  465.     {
  466.         edge = g_edge_length;
  467.         radius = edge * 2.0 / sqrt(3.);
  468.     }
  469.  
  470.     half = 0.5 * radius;    /* inner radius */
  471.     ra = radius;
  472.     ha = half;
  473.  
  474.     f = points;
  475.     add_point(zero, zero,  ra);
  476.     add_point(zero, zero, -ra);
  477.     add_point(zero,  ra, zero);
  478.     add_point(zero, -ra, zero);
  479.     add_point( ra, zero, zero);
  480.     add_point(-ra, zero, zero);
  481.  
  482.     add_point(-ha, -ha, -ha);
  483.     add_point(-ha, -ha,  ha);
  484.     add_point(-ha,  ha, -ha);
  485.     add_point(-ha,  ha,  ha);
  486.     add_point( ha, -ha, -ha);
  487.     add_point( ha, -ha,  ha);
  488.     add_point( ha,  ha, -ha);
  489.     add_point( ha,  ha,  ha);
  490.  
  491.     convert_points();
  492.  
  493.     if (!connected) return;
  494.  
  495.     np[0] = f+8; np[1] = f+2; np[2] = f+12; np[3] = f+1;
  496.     add_poly(4, colors.newface, np, 0);
  497.     np[0] = f+12; np[1] = f+2; np[2] = f+13; np[3] = f+4;
  498.     add_poly(4, colors.newface, np, 0);
  499.     np[0] = f+13; np[1] = f+2; np[2] = f+9; np[3] = f+0;
  500.     add_poly(4, colors.newface, np, 0);
  501.     np[0] = f+9; np[1] = f+2; np[2] = f+8; np[3] = f+5;
  502.     add_poly(4, colors.newface, np, 0);
  503.  
  504.     np[0] = f+6; np[1] = f+1; np[2] = f+10; np[3] = f+3;
  505.     add_poly(4, colors.newface, np, 0);
  506.     np[0] = f+10; np[1] = f+4; np[2] = f+11; np[3] = f+3;
  507.     add_poly(4, colors.newface, np, 0);
  508.     np[0] = f+11; np[1] = f+0; np[2] = f+7; np[3] = f+3;
  509.     add_poly(4, colors.newface, np, 0);
  510.     np[0] = f+7; np[1] = f+5; np[2] = f+6; np[3] = f+3;
  511.     add_poly(4, colors.newface, np, 0);
  512.  
  513.     np[0] = f+12; np[1] = f+4; np[2] = f+10; np[3] = f+1;
  514.     add_poly(4, colors.newface, np, 0);
  515.     np[0] = f+13; np[1] = f+0; np[2] = f+11; np[3] = f+4;
  516.     add_poly(4, colors.newface, np, 0);
  517.     np[0] = f+9; np[1] = f+5; np[2] = f+7; np[3] = f+0;
  518.     add_poly(4, colors.newface, np, 0);
  519.     np[0] = f+8; np[1] = f+1; np[2] = f+6; np[3] = f+5;
  520.     add_poly(4, colors.newface, np, 0);
  521. }
  522.  
  523.  
  524. void create_cuboct(connected)
  525. int connected;
  526. {
  527.     double edge;    /* note: radius = edge length */
  528.     double in;
  529.     index i, j, k;
  530.     coord e;
  531.     index np[4];    /* new polygon */
  532.     index f;
  533.  
  534.     edge = g_edge_length;
  535.  
  536.     /* e is half the edge length of the surounding cube, whose edge is
  537.         sqrt(2) * edge of the cuboct */
  538.     /* (distance from the cuboct's center to the middle of a square edge) */
  539.     in = edge/sqrt(2.);
  540.     e = (coord)in;
  541.  
  542.     f = points;
  543.     for (i = -1; i <= 1; i++)
  544.         for (j = -1; j <= 1; j++)
  545.             for (k = -1; k <= 1; k++)
  546.                 if ((i&&j&&!k) || (i&&!j&&k) || (!i&&j&&k))
  547.                     add_point(i*e, j*e, k*e);
  548.     convert_points();
  549.  
  550.     if (!connected) return;
  551.  
  552.     np[0] = f+1; np[1] = f+6; np[2] = f+9; np[3] = f+4;
  553.     add_poly(4, colors.newface, np, 0);
  554.     np[0] = f+9; np[1] = f+11; np[2] = f+10; np[3] = f+8;
  555.     add_poly(4, colors.newface, np, 0);
  556.     np[0] = f+10; np[1] = f+7; np[2] = f+2; np[3] = f+5;
  557.     add_poly(4, colors.newface, np, 0);
  558.     np[0] = f+2; np[1] = f+3; np[2] = f+1; np[3] = f+0;
  559.     add_poly(4, colors.newface, np, 0);
  560.  
  561.     np[0] = f+7; np[1] = f+11; np[2] = f+6; np[3] = f+3;
  562.     add_poly(4, colors.newface, np, 0);
  563.     np[0] = f+0; np[1] = f+4; np[2] = f+8; np[3] = f+5;
  564.     add_poly(4, colors.newface, np, 0);
  565.  
  566.     add_face1(6, 11, 9);
  567.     add_face1(11, 7, 10);
  568.     add_face1(7, 3, 2);
  569.     add_face1(3, 6, 1);
  570.  
  571.     add_face1(9, 8, 4);
  572.     add_face1(10, 5, 8);
  573.     add_face1(2, 0, 5);
  574.     add_face1(1, 4, 0);
  575. }
  576.  
  577.  
  578. void create_globe()
  579. {
  580.     long radius = 100, phi_div = 4, theta_div = 8;
  581.     int go = 1, event;
  582.     int id;
  583.     long data;
  584.     int add_p, add_f, add_q;
  585.  
  586.     sys_window(34, 6, "Create Globe");
  587.     sys_movecur(1,0);
  588.     sys_say_text("Radius:");
  589.     sys_get_long(radius, 1);
  590.  
  591.     sys_movecur(1,1);
  592.     sys_say_text("Divisions in phi:");
  593.     sys_get_long(phi_div, 2);
  594.  
  595.     sys_movecur(1,2);
  596.     sys_say_text("Divisions in theta:");
  597.     sys_get_long(theta_div, 3);
  598.  
  599.     sys_movecur(3,4);
  600.     sys_boolean(" OK ", 4);
  601.  
  602.     sys_movecur(15,4);
  603.     sys_boolean("Cancel", 5);
  604.     sys_activate(1);
  605.  
  606.     while (go)
  607.     {
  608.         event = sys_read_event(&id, &data);
  609.         switch (event)
  610.         {
  611.         case EV_CANCEL:
  612.             sys_close_window();
  613.             return;
  614.             break;
  615.         case EV_CHECKINT:
  616.         case EV_HITRETURN:
  617.             if (id == 1)
  618.             {
  619.                 if (data > 8000) data = 8000;
  620.                 if (data < 5) data = 5;
  621.                 radius = data;
  622.                 if (event == EV_HITRETURN) sys_activate(2);
  623.             }
  624.             else if (id == 2)
  625.             {
  626.                 if (data > 100) data = 100;
  627.                 if (data < 2) data = 2;
  628.                 phi_div = data;
  629.                 if (event == EV_HITRETURN) sys_activate(3);
  630.             }
  631.             else if (id == 3)
  632.             {
  633.                 if (data > 100) data = 100;
  634.                 if (data < 2) data = 2;
  635.                 theta_div = data;
  636.                 if (event == EV_HITRETURN) go = 0;
  637.             }
  638.             break;
  639.         case EV_HITBUTTON:
  640.             if (id == 4) go = 0;
  641.         }
  642.     }
  643.     sys_close_window();
  644.  
  645.     /* calculate the number of points, faces and quads that will be created */
  646.     add_p = 2 + ((phi_div - 1) * theta_div);
  647.     add_f = 2 * theta_div;
  648.     add_q = (phi_div - 2) * theta_div;
  649.  
  650.     if (!enough_room(add_p, add_f, add_q, 0, 0, 0, 0, 4))
  651.     {
  652.         /* this operation could overflow the undo buffer! */
  653.         if (!tell_user_overflow()) return;
  654.     }
  655.  
  656.     begin_operation();
  657.     create_globe0((coord)radius, phi_div, theta_div);
  658.     end_operation();
  659. }
  660.  
  661.  
  662. void create_globe0(radius, phi_div, theta_div)
  663. coord radius;
  664. int phi_div, theta_div;
  665. {
  666.     index p0, p1;
  667.     index base, line_start;
  668.     int phi, theta;
  669.     double d_phi, d_theta;
  670.     coord x, y, z;
  671.     index np[4];    /* new polygon */
  672.  
  673.     /* add the pole points */
  674.     p0 = points;
  675.     add_point(zero, radius, zero);
  676.     p1 = points;
  677.     add_point(zero, -radius, zero);
  678.  
  679.     base = points;
  680.     d_phi = (PI / phi_div);
  681.     for (phi = 1; phi < phi_div; phi++)
  682.     {
  683.       d_theta = 0.0;
  684.       for (theta = 0; theta < theta_div; theta++)
  685.       {
  686.         x = cos(d_theta) * sin(d_phi) * radius;
  687.         z = sin(d_theta) * sin(d_phi) * radius;
  688.         y = cos(d_phi) * radius;
  689.         /* note that y and z are swapped, our coordinates are LEFT-handed */
  690.         add_point(x, y, z);
  691.         d_theta += (2.0 * PI / theta_div);
  692.       }
  693.       d_phi += (PI / phi_div);
  694.     }
  695.     /* add top triangles */
  696.     for (theta = 0; theta < theta_div; theta++)
  697.         add_face1(p0, base + theta, base + ((theta+1)%theta_div));
  698.     /* add center quads (if any) */
  699.     if (phi_div > 2)
  700.     {
  701.       for (phi = 0; phi < (phi_div-2); phi++)
  702.       {
  703.           line_start = base + (phi*theta_div);
  704.         for (theta = 0; theta < theta_div; theta++)
  705.         {
  706.             np[0] = line_start + theta;
  707.             np[1] = line_start + (theta+1)%theta_div;
  708.             np[2] = np[1] + theta_div;
  709.             np[3] = np[0] + theta_div;
  710.             add_poly(4, colors.newface, np, 0);
  711.         }
  712.       }
  713.     }
  714.     /* add bottom triangles */
  715.       line_start = base + ((phi_div - 2) * theta_div);
  716.     for (theta = 0; theta < theta_div; theta++)
  717.         add_face1(p1, line_start + theta, line_start + ((theta+1)%theta_div));
  718. }
  719.  
  720.  
  721. void normalize()    /* set all points equidistant from their center */
  722. {
  723.     uindex i;
  724.     double cx, cy, cz, radius, d2, scale_factor;
  725.     coord dx, dy, dz;
  726.  
  727.     /* to find the center of the object, we average the location of
  728.         the points */
  729.  
  730.     begin_operation();
  731.  
  732.     find_center(&cx, &cy, &cz);
  733.     find_radius(cx, cy, cz, &radius);
  734.  
  735. #if 0
  736.     printf("center %f %f %f radius %f\n", cx, cy, cz, radius);
  737. #endif
  738.     for (i = 0; i < points; i++)
  739.     {
  740.         dx = point[i].x - cx;
  741.         dy = point[i].y - cy;
  742.         dz = point[i].z - cz;
  743.         d2 = sqrt((double)(dx*dx + dy*dy + dz*dz));
  744.         scale_factor = radius / d2;
  745.         point[i].x = cx + (dx * scale_factor);
  746.         point[i].y = cy + (dy * scale_factor);
  747.         point[i].z = cz + (dz * scale_factor);
  748.         convert_point(i);
  749.     }
  750.  
  751.     end_operation();
  752. }
  753.  
  754.